<?php
require_once(SITE_ROOT . 'class/db/DBHCountry.class.php');
require_once(SITE_ROOT . 'class/db/DBCountry.class.php');
require_once(SITE_ROOT . 'class/db/DBTeam.class.php');
require_once(SITE_ROOT . 'class/db/DBFlag.class.php');
require_once(SITE_ROOT . 'class/db/DBAllianceMember.class.php');
require_once(SITE_ROOT . 'class/bean/Country.class.php');
require_once(SITE_ROOT . 'class/bean/Team.class.php');
require_once(SITE_ROOT . 'class/bean/League.class.php');
require_once(SITE_ROOT . 'class/logic/CoolnessTableRow.class.php');
require_once(SITE_ROOT . 'class/Exceptions.class.php');
require_once(SITE_ROOT . 'lib/PHT.php');

class LogicCoolness {

	private $countries;
	private $visited;
	private $hosted;
	private $cookieset = false;
	
	private static $instance;
	
	// private constructor
	private function __construct() {
		$db = new DBCountry();
		$this->countries = $db->getCountries();
		if (isset($_COOKIE['away'])) {
			$this->visited = unserialize(gzuncompress(base64_decode($_COOKIE['away'])));
			$this->cookieset = true;
		}
		else $this->visited = array();
		if (isset($_COOKIE['home'])) {
			$this->hosted = unserialize(gzuncompress(base64_decode($_COOKIE['home'])));
			$this->cookieset = true;
		}
		else $this->visited = array();
	}

	// the getInstance() method returns a single instance of the object
	public static function getInstance() {
		if(!isset(self::$instance)) {
			self::$instance = new self;
		}
		return self::$instance;
	}
	
	public function hasCookieSet() {
		return $this->cookieset;
	}
	
	public function countUsers() {
		$db = new DBCountry();
		return $db->getActiveUsers();
	}
	
	public function countCountries() {
		return count($this->countries);
	}
	
	public function sumCoolness() {
		$sumCoolness = 0;
		foreach ($this->countries as $country) {
			$sumCoolness = $sumCoolness + $country->getCoolness();
		}
		return $sumCoolness;
	}
	
	public function createCoolnessTable() {
		$table = array();
						
		$db = new DBCountry();
		$date = $db->getDate();
		
		$week1 = $this->getHistory($date, '-1 day');
		$week2 = $this->getHistory($date, '-1 week');
		$week8 = $this->getHistory($date, '-2 weeks');
		$week16 = $this->getHistory($date, '-3 weeks');
		$week28 = $this->getHistory($date, '-4 weeks');
		$week52 = $this->getHistory($date, '-6 weeks');
			
		if (count($this->countries) > 0) {
			foreach ($this->countries as $index => &$country) {
				$row = new CoolnessTableRow($index+1, $country, $week1, $week2, $week8, $week16, $week28, $week52, $this->visited, $this->hosted);
				$table[$country->getCountryID()] = $row;
			}
		}
		return $table;
	}
	
	public function manUpdate($away, $home, $team = null, $cookies = null) {
		if (count($away) <= 0 && count($home) <=0) {
			if ($cookies != false) {
				setcookie ('away', '', time() - 3600);
				setcookie ('home', '', time() - 3600);
			}
			$this->visited = array();
			$this->hosted = array();
		}
		else {
			if (count($away) > 0) {
				if ($cookies != false) setcookie('away', base64_encode(gzcompress(serialize($away))), time()+60*60*24*28);
				$this->visited = $away;
			}
			else {
				if ($cookies != false) setcookie ('away', '', time() - 3600);
				$this->visited = array();
			}
			if (count($home) > 0) {
				if ($cookies != false) setcookie('home', base64_encode(gzcompress(serialize($home))), time()+60*60*24*28);
				$this->hosted = $home;
			}
			else {
				if ($cookies != false) setcookie ('home', '', time() - 3600);
				$this->hosted = array();
			}
		}
		return $this->calculateCoolness($away, $home, $team);
	}
	
	public function autoUpdate($teamID, $cookies = null) {		
		$HT = $_SESSION['HT'];
					
		if ($HT instanceof CHPPConnection) {
			$htTeam = $HT->getTeam($teamID);
			$dbteam = new DBTeam();
			if ($htTeam->isBot()) {
				$dbteam->deleteTeamByID($htTeam->getTeamId());
				$dballiancemember = new DBAllianceMember();
				$dballiancemember->deleteAllianceMembershipByTeamID($teamID);
				$dbflag = new DBFlag();
				$dbflag->deleteFlagsByTeamID($teamID);
				throw new IsBotException();
			}
			else {
				$team = $dbteam->getTeamByID($htTeam->getTeamId());
				$flags['away'] = array();
				$flags['home'] = array();
				
				if (isset($team)) {
					$flags = $HT->getFlags($htTeam->getTeamId(), $this->getTime($team->getUpdate(), "-14 days"));
					foreach ($team->getFlags() as $flag) {
						if ($flag->hasVisited()) {
							$flags['away'][$flag->getCountry()->getCountryId()] = true;
						}
						if ($flag->hasHosted()) {
							$flags['home'][$flag->getCountry()->getCountryId()] = true;
						}
					}
				}
				else {
					$team = new Team();
					$team->setTeamID($htTeam->getTeamId());
					
					$flags = $HT->getFlags($htTeam->getTeamId());
					
					/*$awayflags = $HT->getFlagsAway($htTeam->getTeamId());
					$away = array();
					for ($i=1; $i<=$awayflags->getFlagNumber(); $i++) {
						$away[$awayflags->getLeagueOfFlag($i)->getId()] = true;
					}
					
					$homeflags = $HT->getFlagsHome($htTeam->getTeamId());
					$home = array();
					for ($i=1; $i<=$homeflags->getFlagNumber(); $i++) {
						$home[$homeflags->getLeagueOfFlag($i)->getId()] = true;
					}*/
				}
				$team = $this->manUpdate($flags['away'], $flags['home'], $team, $cookies);
				
				$team->setName($htTeam->getTeamName());
				$team->setUpdate(time());
				$team->setUserID($htTeam->getUserId());
				$team->setUserName($htTeam->getLoginName());
				$team->setActivationDate($htTeam->getActivationDate());
				
				$league = new League();
				if ($htTeam->isLeagueLevelAvailable()) {
					$league->setLeagueID($htTeam->getLeagueLevelId());
				}
				else if ($team->getLeague() != null) {
					$league = $team->getLeague();
				}
				else throw new LeagueNotAvailableException($team);
				$team->setLeague($league);
				
				$dbteam->saveTeam($team);
				
				$HT->clearFlags($teamID);
				$HT->clearSeniorTeamMatches($teamID);
				$HT->clearSeniorTeamArchiveMatches($teamID);
				$HT->clearSeniorMatchesDetails();				
				$HT->clearTeams();
				return $team;
			}
		}
		else throw new Exception();
	}
	
	public function dbUpdate($teamID) {
		$dbteam = new DBTeam();
		$team = $dbteam->getTeamByID($teamID);
		
		if (isset($team)) {
			if (date("Y-m-d", $team->getUpdate()) != "1970-01-01") {
				foreach ($team->getFlags() as $flag) {
					if ($flag->hasVisited()) {
						$flags['away'][$flag->getCountry()->getCountryId()] = true;
					}
					if ($flag->hasHosted()) {
						$flags['home'][$flag->getCountry()->getCountryId()] = true;
					}
				}
				return $this->manUpdate($flags['away'], $flags['home'], $team, true);
			}
			else throw new Exception("The team wasn't found in the database. Please login and update with the TeamID.");
		}
		else throw new Exception("The team wasn't found in the database. Please login and update with the TeamID.");
	}
	
	public function cookieUpdate() {
		return $this->calculateCoolness($this->visited, $this->hosted);
	}
		
	private function calculateCoolness($away, $home, $team = null) {
		if ($team === null) {
			$team = new Team();
		}
		else $team->resetRatings();
		
		$flags = new ArrayObject();
		
		foreach ($this->countries as $country) {
			$flag = new Flag();
			$flag->setCountry($country);
			if ($away[$country->getCountryID()] == true) {
				$flag->setVisited(true);
				$this->calculateAwayCoolness($team, $country);
				$this->calculatePlusCoolness($team, $country);
			}
			if ($home[$country->getCountryID()] == true) {
				$flag->setHosted(true);
				$this->calculateHomeCoolness($team, $country);
				$this->calculatePlusCoolness($team, $country);
			}
			if ($away[$country->getCountryID()] == true && $home[$country->getCountryID()] == true) {
				$this->calculateOrCoolness($team, $country);
				$this->calculateAndCoolness($team, $country);
			}
			else if ($away[$country->getCountryID()] == true && $home[$country->getCountryID()] == false) {
				$this->calculateOrCoolness($team, $country);
			}
			if ($home[$country->getCountryID()] == true && $away[$country->getCountryID()] == false) {
				$this->calculateOrCoolness($team, $country);
			}
			if ($flag->hasVisited() || $flag->hasHosted()) {
				$flags->append($flag);
			}				
		}
		
		$team->setFlags($flags);		
		
		return $team;
	}
	
	private function calculateAwayCoolness(&$team, &$country) {
		$team->setAwayCoolness($team->getAwayCoolness() + $country->getCoolness());
		$team->setAwayFlags($team->getAwayFlags() + 1);
		if ($team->getAwayCountry() !== null) {
			if ($country->getCoolness() > $team->getAwayCountry()->getCoolness()) {
				$team->setAwayCountry($country);
			}
		}
		else $team->setAwayCountry($country);
	}
	
	private function calculateHomeCoolness(&$team, &$country) {
		$team->setHomeCoolness($team->getHomeCoolness() + $country->getCoolness());
		$team->setHomeFlags($team->getHomeFlags() + 1);
		if ($team->getHomeCountry() !== null) {
			if ($country->getCoolness() > $team->getHomeCountry()->getCoolness()) {
				$team->setHomeCountry($country);
			}
		}
		else $team->setHomeCountry($country);
	}
	
	private function calculateAndCoolness(&$team, &$country) {
		$team->setAndCoolness($team->getAndCoolness() + $country->getCoolness());
		$team->setAndFlags($team->getAndFlags() + 1);
		if ($team->getAndCountry() !== null) {
			if ($country->getCoolness() > $team->getAndCountry()->getCoolness()) {
				$team->setAndCountry($country);
			}
		}
		else $team->setAndCountry($country);
	}
	
	private function calculateOrCoolness(&$team, &$country) {
		$team->setOrCoolness($team->getOrCoolness() + $country->getCoolness());
		$team->setOrFlags($team->getOrFlags() + 1);
		if ($team->getOrCountry() !== null) {
			if ($country->getCoolness() > $team->getOrCountry()->getCoolness()) {
				$team->setOrCountry($country);
			}
		}
		else $team->setOrCountry($country);
	}
	
	private function calculatePlusCoolness(&$team, &$country) {
		$team->setPlusCoolness($team->getPlusCoolness() + $country->getCoolness());
		$team->setPlusFlags($team->getPlusFlags() + 1);
		if ($team->getPlusCountry() !== null) {
			if ($country->getCoolness() > $team->getPlusCountry()->getCoolness()) {
				$team->setPlusCountry($country);
			}
		}
		else $team->setPlusCountry($country);
	}
	
	private function getHistory($date, $timeshift) {
		$db = new DBHCountry();
		return $db->getCountries($this->getTime($date, $timeshift));
	}
	
	private function getTime($date, $shift) {
		return date("Y-m-d" , strtotime($shift, $date));
	}

}

?>